package com.lastproject.web.bean;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.lastproject.dto.AnswerDTO;
import com.lastproject.dto.QuestionDTO;
import com.lastproject.dto.QuestionOptionDTO;
import com.lastproject.dto.QuestionOptionStatsDTO;
import com.lastproject.dto.QuestionStatsDTO;
import com.lastproject.dto.SurveyDTO;
import com.lastproject.dto.UserDTO;
import com.lastproject.ejb.dao.AnswerDAORemote;
import com.lastproject.ejb.dao.QuestionDAORemote;
import com.lastproject.ejb.dao.QuestionOptionDAORemote;
import com.lastproject.ejb.dao.SurveyDAORemote;

@ManagedBean
@RequestScoped
public class SurveyStatsQTableData {

	private DataModel<SurveyStatsQBean> filterModel = null;

	@ManagedProperty(value = "#{surveyStatsBean}")
	private SurveyStatsBean survStatsBeanObj; // cb

	private SurveyStatsQBean[] questionList; // customers

	@EJB
	private SurveyDAORemote survDAOr;

	@EJB
	private QuestionDAORemote questionDAOr;

	@EJB
	private QuestionOptionDAORemote questionOptionDAOr;

	@EJB
	private AnswerDAORemote answerDAOr;

	// FONTS
	private static Font catFont = new Font(Font.FontFamily.TIMES_ROMAN, 18,
			Font.BOLD);
	private static Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 16,
			Font.BOLD);

	// private static Font smallBold = new Font(Font.FontFamily.TIMES_ROMAN, 12,
	// Font.BOLD);

	@PostConstruct
	public void postConstr() {

		List<QuestionDTO> qList = questionDAOr
				.getQuestionListBySurveyId(survStatsBeanObj.getIdSurv());

		QuestionStatsDTO[] qStatDTOArr = new QuestionStatsDTO[qList.size()];

		for (int i = 0; i < qList.size(); i++) {
			qStatDTOArr[i] = new QuestionStatsDTO(qList.get(i));
		}

		questionList = new SurveyStatsQBean[qList.size()];

		for (int i = 0; i < questionList.length; i++) {
			questionList[i] = new SurveyStatsQBean(qStatDTOArr[i]);

			int nbTotalAnswers = 0; // A

			List<QuestionOptionDTO> qoDTOList = questionOptionDAOr
					.getQuestionOptionNumericListByQuestionId(questionList[i]
							.getQuestionStatsDTO().getId());

			float[] nbAnswers = new float[qoDTOList.size()]; // A
			int nbAnswerIndex = 0;

			QuestionOptionStatsDTO[] qosDTOArr = new QuestionOptionStatsDTO[qoDTOList
					.size()];

			for (int j = 0; j < qoDTOList.size(); j++) {
				qosDTOArr[j] = new QuestionOptionStatsDTO(qoDTOList.get(j));
			}

			// Pune array-ul de QuestionOptionStatsDTO facut mai sus in obiectul
			// questionList[i]
			QuestionStatsDTO qsdto = questionList[i].getQuestionStatsDTO();
			qsdto.setQuestionOptionStatsArr(qosDTOArr);
			questionList[i].setQuestionStatsDTO(qsdto);

			for (QuestionOptionStatsDTO q : questionList[i]
					.getQuestionStatsDTO().getQuestionOptionStatsArr()) {

				// displaying the answers for this option

				List<AnswerDTO> aDTOList = answerDAOr
						.getAnswersByQuestionOptionId(q.getId());
				if (q.getType().equals("grade")) {

					if (aDTOList.size() > 0) {
						for (int k = 0; k < aDTOList.size(); k++) {
							if (nbAnswers[nbAnswerIndex] == 0) {
								nbAnswers[nbAnswerIndex] = 0 + Integer
										.parseInt(aDTOList.get(k)
												.getPersonalAnswer().toString());
							} else {
								nbAnswers[nbAnswerIndex] = nbAnswers[nbAnswerIndex]
										+ Integer
												.parseInt(aDTOList.get(k)
														.getPersonalAnswer()
														.toString());

							}
						}
						nbAnswers[nbAnswerIndex] = (float) nbAnswers[nbAnswerIndex]
								/ aDTOList.size();

					} else {
						nbAnswers[nbAnswerIndex] = 0;
					}
					nbTotalAnswers = nbTotalAnswers + aDTOList.size();

					// End of GRADE part
				} else {
					// A
					if (aDTOList.size() > 0) {

						nbAnswers[nbAnswerIndex] = aDTOList.size();
					} else {
						nbAnswers[nbAnswerIndex] = 0;
					}
					nbTotalAnswers = nbTotalAnswers + aDTOList.size();
				}
				nbAnswerIndex++;

			} // END of QuestionOption section

			// Seteaza numarul total de raspunsuri la obiectul QuestionStatsDTO
			QuestionStatsDTO qsDTO = questionList[i].getQuestionStatsDTO();
			qsDTO.setAnswerListSize(qsDTO.getQuestionOptionStatsArr().length);

			qsDTO.setNbAnswers(nbAnswers);

			qsDTO.setNbTotalAnswers(nbTotalAnswers);
			questionList[i].setQuestionStatsDTO(qsDTO);

			QuestionStatsDTO questionStatDTO = questionList[i]
					.getQuestionStatsDTO();
			QuestionOptionStatsDTO[] questionOptionStatsDTOArr = questionStatDTO
					.getQuestionOptionStatsArr();

			for (int j = 0; j < questionOptionStatsDTOArr.length; j++) {

				if (!questionOptionStatsDTOArr[j].getType().equals("grade")) {
					float currentValue = (float) questionList[i]
							.getQuestionStatsDTO().getAnswerInList(j);
					float totalValue = (float) questionList[i]
							.getQuestionStatsDTO().getNbTotalAnswers();
					if (totalValue == 0) {
						questionOptionStatsDTOArr[j].setPercAnswered("0");
					} else {
						DecimalFormat myFormatter = new DecimalFormat("###.##");
						float percAns = (((float) currentValue) / ((float) totalValue)) * 100;
						String val = myFormatter.format(percAns);
						questionOptionStatsDTOArr[j]
								.setPercAnswered(val + " %");
					}
				} else {
					float currentValue = (float) questionList[i]
							.getQuestionStatsDTO().getAnswerInList(j);
					float totalValue = (float) questionList[i]
							.getQuestionStatsDTO().getNbTotalAnswers();
					if (totalValue == 0) {
						questionOptionStatsDTOArr[j].setPercAnswered("0");
					} else {
						DecimalFormat myFormatter = new DecimalFormat("###.##");
						String val = myFormatter.format(currentValue);
						questionOptionStatsDTOArr[j].setPercAnswered(val + " ");
					}
				}
			}
			// Rank question options

			// End of Rank question options
		}
		filterModel = new ArrayDataModel<SurveyStatsQBean>(questionList);
	}

	public SurveyStatsQTableData() {

	}

	public SurveyStatsBean getSurvStatsBeanObj() {
		return survStatsBeanObj;
	}

	public void setSurvStatsBeanObj(SurveyStatsBean survStatsBeanObj) {
		this.survStatsBeanObj = survStatsBeanObj;
	}

	public DataModel<SurveyStatsQBean> getQuestionList() {
		return filterModel;
	}

	public void exportToXls() {
		SurveyDTO surveyDTO = survStatsBeanObj.getSurveyDTO();
		UserDTO userDTO = survStatsBeanObj.getUserDTO();
		String filename = "SurveyInterrog" + userDTO.getLastname()
				+ userDTO.getFirstname() + surveyDTO.getTitle() + ".xls";

		try {

			HSSFWorkbook wb = new HSSFWorkbook();
			HSSFSheet sheet = wb.createSheet(filename);

			HSSFRow row = sheet.createRow(0);
			row.createCell(0).setCellValue("Question");
			row.createCell(1).setCellValue("Options");
			row.createCell(2).setCellValue("Answers");

			QuestionStatsDTO qsDTO;
			QuestionOptionStatsDTO[] qosDTOArr;
			int indexRow = 1;

			for (int i = 0; i < questionList.length; i++) {
				row = sheet.createRow(indexRow);

				qsDTO = questionList[i].getQuestionStatsDTO();

				row.createCell(0).setCellValue(qsDTO.getText());

				qosDTOArr = qsDTO.getQuestionOptionStatsArr();

				String questionOptions;

				for (int j = 0; j < qosDTOArr.length; j++) {
					if (j > 0) {
						row = sheet.createRow(indexRow);
					} else {
						indexRow++;
					}
					questionOptions = qosDTOArr[j].getQuestionOptionDTO()
							.getText();

					row.createCell(1).setCellValue(questionOptions);

					row.createCell(2).setCellValue(
							qosDTOArr[j].getPercAnswered());

					if (j > 0) {
						row = sheet.createRow(++indexRow);
					} else {
						row = sheet.createRow(indexRow);
					}

				}

			}

			FacesContext context = FacesContext.getCurrentInstance();
			HttpServletResponse res = (HttpServletResponse) context
					.getExternalContext().getResponse();
			res.setContentType("application/vnd.ms-excel");

			res.setHeader("Content-disposition", "attachment;filename="
					+ filename);

			ServletOutputStream out = res.getOutputStream();
			wb.write(out);
			out.flush();
			out.close();
			FacesContext.getCurrentInstance().responseComplete();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// PDF
	public void exportToPdf() {

		SurveyDTO surveyDTO = survStatsBeanObj.getSurveyDTO();
		UserDTO userDTO = survStatsBeanObj.getUserDTO();

		String filename = "SurveyInterrog" + userDTO.getLastname()
				+ userDTO.getFirstname() + surveyDTO.getTitle() + ".pdf";
		Document document = new Document();

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");

		System.out.println("SurveyToPdfBean, title: " + surveyDTO.getTitle());
		System.out.println("SurveyToPdfBean, description: "
				+ surveyDTO.getDescription());

		String startD = simpleDateFormat.format(surveyDTO.getStartDate());
		String endD = simpleDateFormat.format(surveyDTO.getEndDate());
		System.out.println("SurveyToPdfBean, startDate: " + startD);
		System.out.println("SurveyToPdfBean, endDate: " + endD);

		System.out.println("SurveyToPdfBean, idUser: " + surveyDTO.getIdUser());
		System.out.println("SurveyToPdfBean, idSurvey: " + surveyDTO.getId());
		System.out.println();
		System.out.println("SurveyToPdfBean, username: "
				+ userDTO.getFirstname() + " " + userDTO.getLastname());

		try {

			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			PdfWriter.getInstance(document, baos);

			document.open();
			addPdfHeader(document, survStatsBeanObj);

			addPdfTable(document, questionList);

			document.close();

			// Setting output stream
			FacesContext context = FacesContext.getCurrentInstance();
			HttpServletResponse response = (HttpServletResponse) context
					.getExternalContext().getResponse();

			// setting the content type
			response.setContentType("application/pdf");
			response.setHeader("Content-disposition", "attachment;filename="
					+ filename);

			// the contentlength
			response.setContentLength(baos.size());

			// write ByteArrayOutputStream to the ServletOutputStream
			OutputStream os = response.getOutputStream();
			baos.writeTo(os);
			os.flush();
			os.close();

		} catch (FileNotFoundException | DocumentException e) {
			e.printStackTrace();
		} catch (Exception ioe) {
			ioe.printStackTrace();
		}

	}// End of Export to PDF

	private void addPdfTable(Document document, SurveyStatsQBean[] questionList)
			throws BadElementException {
		PdfPTable table = new PdfPTable(3);

		PdfPCell c1;

		c1 = new PdfPCell(new Phrase("Question"));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);

		c1 = new PdfPCell(new Phrase("Options"));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);
		//
		c1 = new PdfPCell(new Phrase("Answers"));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);

		table.setHeaderRows(1);

		QuestionOptionStatsDTO[] qosArr;

		for (int i = 0; i < questionList.length; i++) {

			table.addCell(questionList[i].getQuestionStatsDTO()
					.getQuestionDTO().getText());

			qosArr = questionList[i].getQuestionStatsDTO()
					.getQuestionOptionStatsArr();

			createList(table, qosArr);

		}

		try {
			document.add(table);
		} catch (DocumentException e) {
			e.printStackTrace();
		}

	}

	private void createList(PdfPTable table, QuestionOptionStatsDTO[] qosArr) {

		StringBuilder qOptString = new StringBuilder();
		StringBuilder qPercString = new StringBuilder();

		for (int j = 0; j < qosArr.length; j++) {
			if (j < (qosArr.length - 1)) {
				qOptString.append(qosArr[j].getText() + "\n");
				qPercString.append(qosArr[j].getPercAnswered() + " \n");
			} else {
				qOptString.append(qosArr[j].getText());
				qPercString.append(qosArr[j].getPercAnswered() + " ");
			}

		}
		PdfPCell c1;

		c1 = new PdfPCell(new Phrase(qOptString.toString()));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);

		c1 = new PdfPCell(new Phrase(qPercString.toString()));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);

	}

	private void addPdfHeader(Document document,
			SurveyStatsBean survStatsBeanObj) throws DocumentException {
		SurveyDTO surveyDTO = survStatsBeanObj.getSurveyDTO();
		UserDTO userDTO = survStatsBeanObj.getUserDTO();

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");

		Paragraph preface = new Paragraph();
		// We add one empty line
		addEmptyLine(preface, 1);
		// Lets write a big header
		preface.add(new Paragraph("Survey interpretation report", catFont));

		addEmptyLine(preface, 2);
		// Will create: Report generated by: _name, _date
		preface.add(new Paragraph("Title: " + surveyDTO.getTitle(), subFont));
		addEmptyLine(preface, 1);

		preface.add(new Paragraph("Description: " + surveyDTO.getDescription(),
				subFont));
		addEmptyLine(preface, 1);

		String startD = simpleDateFormat.format(surveyDTO.getStartDate());
		String endD = simpleDateFormat.format(surveyDTO.getEndDate());
		preface.add(new Paragraph("Period: " + startD + " - " + endD, subFont));
		addEmptyLine(preface, 1);

		preface.add(new Paragraph("Created by: " + userDTO.getFirstname() + " "
				+ userDTO.getLastname(), subFont));
		addEmptyLine(preface, 3);

		document.add(preface);
	}

	private void addEmptyLine(Paragraph paragraph, int number) {
		for (int i = 0; i < number; i++) {
			paragraph.add(new Paragraph(" "));
		}
	}

}
